package socklib

import (
	"bytes"
	"errors"
	"io"
)

/**
数据包协议
样例
*/

type (
	DataFrameFactory struct {
		Head    byte   //0x78
		Ver     byte   //0x01
		DataLen []byte //数据长度
		Data    []byte //数据
		Crc     []byte //数据校验,仅对数据区域部分做CRC32校验
		End     byte   //0xa5
	}
)

//
var (
	//默认数据帧工厂
	DefaultDataFrameFactory = NewDataFrameFactory(0x78, 0x01, 0xa5)
)

//
func NewDataFrameFactory(head, ver, end byte) *DataFrameFactory {
	return &DataFrameFactory{
		Head: head,
		End:  end,
		Ver:  ver,
	}
}

//按照协议约定拼装
func (df *DataFrameFactory) BuildFrame(data []byte) []byte {
	buf := bytes.NewBuffer(nil)
	buf.WriteByte(df.Head)
	buf.WriteByte(df.Ver)
	buf.Write(Uint32ToBytes(uint32(len(data))))
	buf.Write(data)
	buf.Write(Crc(data)[:4])
	buf.WriteByte(df.End)
	return buf.Bytes()
}

//从流中读取数据
func (df *DataFrameFactory) ReadFrame(reader io.Reader) ([]byte, error) {
	head := make([]byte, 6)
	_, err := io.ReadFull(reader, head)
	if err != nil {
		return nil, err
	}
	if head[0] != df.Head || head[1] != df.Ver {
		return nil, errors.New("头部格式不符合要求")
	}
	dataLen := int(BytesToUint32(head[2:])) + 5
	body := make([]byte, dataLen)
	_, err = io.ReadFull(reader, body)
	if err != nil {
		return nil, err
	}
	if body[dataLen-1] != df.End {
		return nil, errors.New("尾部格式不符合要求")
	}
	if !bytes.Equal(body[dataLen-5:dataLen-1],
		Crc(body[:dataLen-5])) {
		return nil, errors.New("校验失败")
	}
	return body[:dataLen-5], nil
}
